﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AL100.BankApplication.BLL
{



    /// <summary>
    /// Base class for all Account calculation commands.
    /// </summary>
    public class CommandBase<T> : ICommand where T : AccountBase
    {
        public delegate double CalculationDelegate(double source, double amount);

        protected CalculationDelegate   _calculationDelegate;
        protected CalculationDelegate   _cancellationDelegate;

        protected T           _source;
        protected Operator              _operator;
        protected double                _amount;

        /// <summary>
        /// Initializes a new instance of the <see cref="CommandBase&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="op">The operator.</param>
        /// <param name="amount">The amount.</param>
        public CommandBase(T source, Operator op, double amount)
        {
            _source         = source;
            _operator       = op;
            _amount         = amount;

            // setup the calculation delegates
            SetupDelegates(); 
        }


        /// <summary>
        /// Setups the calculation delegates.
        /// </summary>
        protected void SetupDelegates()
        {
            switch (_operator)
            {
                case Operator.Add:
                    _calculationDelegate    = new CalculationDelegate(add);
                    _cancellationDelegate   = new CalculationDelegate(substract);
                    break;

                case Operator.Substract:
                    _calculationDelegate    = new CalculationDelegate(substract);
                    _cancellationDelegate   = new CalculationDelegate(add);
                    break;
                    
                case Operator.Multiply:
                    _calculationDelegate    = new CalculationDelegate(multiply);
                    _cancellationDelegate   = new CalculationDelegate(divide);
                    break;

                case Operator.Divide:
                    _calculationDelegate    = new CalculationDelegate(divide);
                    _cancellationDelegate   = new CalculationDelegate(multiply);
                    break;
                
                default:
                    break;
            }
        }


       

        /// <summary>
        /// Executes the command on the specified target.
        /// </summary>
        /// <param name="target">The target's Type.</param>
        public virtual void Execute()
        {
           _source.Balance =  _calculationDelegate(_source.Balance, _amount);
        }

        /// <summary>
        /// Unexecutes the command on the specified target.
        /// </summary>
        /// <param name="target">The target's Type.</param>
        public virtual void Unexecute()
        {
            _source.Balance = _cancellationDelegate(_source.Balance, _amount);
        }

        /// <summary>
        /// Gets the amount.
        /// </summary>
        public double Amount
        {
            get { return _amount;   }
        }

        /// <summary>
        /// Gets the operator.
        /// </summary>
        public Operator Operator
        {
            get { return _operator; }
        }


        #region -- Calculations --


        protected double add(double source, double amount)
        {
            return source + amount;
        }

        protected double substract(double source, double amount)
        {
            return source - amount;
        }

        protected double multiply(double source, double amount)
        {
            return source * amount;
        }

        protected double divide(double source, double amount)
        {
            return source / amount;
        }

        #endregion
    }


    













}
